﻿namespace NetOwls.Tutorials.Mqtt.Common.Publishers
{
    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using MQTTnet;

    /// <summary>
    ///     提供了基于 MQTT 服务发布消息的方法。
    /// </summary>
    /// <seealso>
    ///     <cref>IMessagePublisher</cref>
    /// </seealso>
    /// <seealso>
    ///     <cref>Common.IMqttConnection</cref>
    /// </seealso>
    /// <seealso>
    ///     <cref>System.Threading.Tasks.Task</cref>
    /// </seealso>
    public class MessagePublisher : IMessagePublisher
    {
        #region Constructors

        /// <summary>
        ///     用于初始化一个 <see cref="MessagePublisher" /> 对象实例
        /// </summary>
        /// <param name="connection">
        ///     MQTT 服务连接对象。
        ///     <para>
        ///         实现了
        ///         <see>
        ///             <cref>IMqttConnection</cref>
        ///         </see>
        ///         接口的对象实例。
        ///     </para>
        /// </param>
        /// <seealso>
        ///     <cref>Common.IMqttConnection</cref>
        /// </seealso>
        public MessagePublisher(IMqttConnection connection)
        {
            Connection = connection;
        }

        #endregion

        #region Properties

        #region IMessagePublisher Implements

        /// <summary>
        ///     获取 MQTT 服务连接对象。
        /// </summary>
        public IMqttConnection Connection { get; }

        #endregion

        #endregion

        #region Methods

        #region IMessagePublisher Implements

        /// <summary>
        ///     发布消息。
        /// </summary>
        /// <param name="message">
        ///     消息内容。
        /// </param>
        /// <returns>
        ///     <see>
        ///         <cref>Task</cref>
        ///     </see>
        ///     类型的对象实例。
        /// </returns>
        /// <seealso>
        ///     <cref>System.Threading.Tasks.Task</cref>
        /// </seealso>
        public virtual async Task PublishAsync(string message)
        {
            await InternalPublishAsync(message);
        }

        #endregion

        #endregion

        #region Protected Methods

        /// <summary>
        ///     尝试发布消息。
        /// </summary>
        /// <param name="message">
        ///     需要发布的消息内容。
        /// </param>
        /// <returns>
        ///     <see>
        ///         <cref>Task</cref>
        ///     </see>
        ///     类型的对象实例。
        /// </returns>
        /// <seealso>
        ///     <cref>System.Threading.Tasks.Task</cref>
        /// </seealso>
        protected virtual async Task InternalPublishAsync(string message)
        {
            if (string.IsNullOrWhiteSpace(message))
                Trace.TraceInformation("未知的消息，取消发布。");
            else
                try
                {
                    await Connection.ConnectAsync();
                    var msgBuilder = new MqttApplicationMessageBuilder()
                        .WithAtLeastOnceQoS()
                        .WithTopic("topic/testings")
                        .WithPayload(message);
                    await Connection.Client.PublishAsync(msgBuilder.Build());
                }
                catch (Exception error)
                {
                    Trace.TraceError($"尝试发布消息：{message} 时，引发了一个 {error.GetType().FullName} 类型的异常：{error.Message}");
                }
        }

        #endregion
    }
}